using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using UnityEngine;

namespace BlockOS.Console
{
    public class GameConsole
    {
        public Dictionary<string, Command> commands = new();

        public Action<string> messageReceiver;

        private readonly Regex commandSplitRegex = new("\\s+(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)+");
        private readonly Regex quoted = new("(?<=\").*?(?=\")");


        private readonly IGame game;

        public GameConsole(IGame game)
        {
            this.game = game;
        }

        public void RegistCmd(string name, Command cmd)
        {
            commands.Add(name, cmd);
        }

        public IEnumerator RunCmd(string cmdStr)
        {
            messageReceiver($"Input>{cmdStr}");
            var input =  commandSplitRegex.Split(cmdStr).Select((str) =>
            {
                var match = quoted.Match(str);
                return match.Success ? match.Value : str;
            }).ToArray();
            

            if (commands.TryGetValue(input[0], out Command cmd))
            {
                if (input.Length - 1 > cmd.parameterCount)
                {
                    messageReceiver(GetColorMessage("yellow", $"Parameter count exceed. expect '{cmd.parameterCount}', got '{input.Length - 1}'"));
                    yield return cmd.Call(game, input[1..]);
                }
                else if (input.Length - 1 < cmd.parameterCount)
                {
                    messageReceiver(GetColorMessage("red", $"Too few parameters. expect '{cmd.parameterCount}', got '{input.Length - 1}'"));
                }
                else
                {
                    yield return cmd.Call(game, input[1..]);
                }
            }
            else
            {
                messageReceiver(GetColorMessage("red", $"command '{input[0]}' not found"));
            }
        }

        public void PutMessage(string message)
        {
            messageReceiver(message);
        }

        public string GetColorMessage(string colorCode, string message)
        {
            return $"<color={colorCode}>{message}</color>";
        }
    }
}
